import urllib, urllib2
import Cookie
import re
import datetime

# xbmc-hockey-streams
# author: craig mcnicholas
# contact: craig@designdotworks.co.uk

# Represents a login exception class which is thrown if there
# is an issue parsing or logging into a hockeystreams account
class LoginException(Exception):

    # Creates a new instance of the login exception
    def __init__(self, value):
        self.value = value

    # Overrides this classes string value
    def __str__(self):
        return repr(self.value)

# Represents an event between two teams on a given date
class Event():
    def __init__(self, homeTeam, awayTeam, url):
        self.homeTeam = homeTeam
        self.awayTeam = awayTeam
        self.url = url

    # Overrides this classes string value
    def __str__(self):
        return repr(self.homeTeam + ' vs ' + self.awayTeam + ' @ ' + self.url)

# Represents a team (sometimes can be an event if hockeystreams sasys so)
class Team():
    def __init__(self, name, url):
        self.name = name
        self.url = url

    # Overrides this classes string value
    def __str__(self):
        return repr(self.name + ' @ ' + self.url)

# Method to attempt a login to a hockeystreams account
# @param username the username to login with
# @param password the password to login with
# @throws LoginException when a login fails due to parsing or an incorrect account
# @return the hockeystreams hspass token to use for subsequent requests
def login(username, password):
    # Setup login request data
    data = urllib.urlencode({
        'username': username,
        'password': password
    })

    # Get login response
    request = setupRequest('https://www4.hockeystreams.com/scripts/login.php')
    response = urllib2.urlopen(request, data)
    page = response.read()
    response.close()

    # Check the login was successful
    if page.lower() != 'loggedin':
        raise LoginException('Username or password was incorrect')

    # Get the hspass value
    cookie = Cookie.SimpleCookie(response.info().getheader('Set-Cookie'))
    cookieHspass = cookie['hspass']
    if cookieHspass == None:
        raise LoginException('Failed to retrieve hspass cookie')
    hspass = cookieHspass.value
    if hspass == None or len(hspass) < 1:
        raise LoginException('Hspass cookie value was null or empty')
    
    return hspass

# Method to retrieve available archived dates for hockey streams
# @param username the username to login with
# @param token the token to login with
# @return a list of available dates
def availableDates(username, token):
    # Get response for available dates
    request = setupRequest('http://www4.hockeystreams.com/on-demand', username, token)
    response = urllib2.urlopen(request)
    page = response.read()
    response.close()

    # parse the available dates from javascript
    # looking for the 'var availableDates' variable which is set
    # with an array of dates in the format 'dd-mm-yyyy'
    matches = re.compile('(?:(?:"([0-9]{1,2}\-[0-9]{1,2}\-[0-9]{4})"),?)').findall(page);
    dates = []
    for match in matches:
        parts = match.split('-')
        day = int(parts[0])
        month = int(parts[1])
        year = int(parts[2])
        dates.append(datetime.date(year, month, day))

    return dates

# Method to retrieve available teams for hockey streams
# @param username the username to login with
# @param token the token to login with
# @return a list of teams
def teams(username, token):
    # Get response for available teams and events
    request = setupRequest('http://www4.hockeystreams.com/on-demand', username, token)
    response = urllib2.urlopen(request)
    page = response.read()
    response.close()

    # parse the available teams from html, looking for the following
    # <select name="viewbyteam" class="viewbyteam input" style="...">

    #   <option value="">- View by Team/Event -</option>
    #   <option value="Boston+Bruins" >Boston Bruins</option>
    #   <option value="Buffalo+Sabres" >Buffalo Sabres</option>
    matches = re.compile('<option value="([^"]+)" ?>([^<]+)</option>').findall(page)
    teams = []
    for match in matches:
        teams.append(Team(match[1], match[0]))
    
    return teams

# Method to get the events for a given date
# @param username the username to login with
# @param token the token to login with
# @param date a date instance to return the events for
# @return a list of events
def eventsForDate(username, token, date):
    # Create url for events for a given date, the date format
    # for the url is 'mm-dd-yyyy'
    year = str(date.year)
    month = '%02d' % (date.month,)
    day = '%02d' % (date.day,)
    url = 'http://www4.hockeystreams.com/on-demand/date/' + month + '-' + day + '-' + year
    
    # Get response for events
    request = setupRequest(url, username, token)
    response = urllib2.urlopen(request)
    page = response.read()
    response.close()

    return __parseEvents(page)

# Method to get the events for a given team
# @param username the username to login with
# @param token the token to login with
# @param teamUrl a team url to return the events for
# @return a list of events
def eventsForTeam(username, token, teamUrl):
    # Create url for team events, the format
    # for the url is http://www4.hockeystreams.com/on-demand/team/<team url>
    url = 'http://www4.hockeystreams.com/on-demand/team/' + teamUrl
    
    # Get response for events
    request = setupRequest(url, username, token)
    response = urllib2.urlopen(request)
    page = response.read()
    response.close()

    return __parseEvents(page)

# Method to parse an events page response
# and return the events found in the page
# @param the page html to parse
# @return a list of events
def __parseEvents(page):
    # parse the available events
    # looking for the following chunk of html
    # <div>
    #   <div class="calendar_inner" style="...">Boston Bruins</div>
    #   <div class="calendar_inner" style="...">Washington Capitals</div>
    #   <div class="calendar_inner" style="...">
    #      <a style="..." href="/on-demand/boston+bruins-vs-washington+capitals-04-14-2012/6234" class="ondemand">Watch</a>
    #   </div>
    matches = re.compile('(?:<div class="calendar_inner" style="[^"]*">([^<]*)</div>[^<]*<div class="calendar_inner" style="[^"]*">([^<]*)</div>[^<]*<div class="calendar_inner" style="[^"]*">[^<]*<a style="[^"]*" href="([^"]*)" class="ondemand">Watch</a>)').findall(page);
    events = []
    for match in matches:
        events.append(Event(match[0], match[1], match[2]))

    return events

# Method to get the direct stream url for an event
# @param username the username to login with
# @param token the token to login with
# @param event the event instance to find the direct stream url for
# @return the url direct to the wmv stream or None if not found
def eventStream(username, token, event):
    # Create url for the stream page for windows media
    url = 'http://www4.hockeystreams.com' + event.url + '/windows_media'

    # Get response for event stream
    request = setupRequest(url, username, token)
    response = urllib2.urlopen(request)
    page = response.read()
    response.close()

    # check if we have a windows media stream
    matches = re.compile('Windows Media \(LQ\)').findall(page)
    if len(matches) < 1:
        return None

    # parse the available stream
    # looking for the following chunk of html
    # <input type="text" class="input direct_link" style="..." value="http://.../" />
    matches = re.compile('<input type="text" class="input direct_link" style="[^"]*" value="([^"]*)" />').findall(page);
    if len(matches) < 1:
        return None
    else:
        return matches[0]

# Method to setup a request object to hockeystreams
# @param url the url to setup the request to
# @param hsuser [optional] the username to pass as a cookie
# @param hspass [optional] the password to pass as a cookie
# @return an urllib2.Request object
def setupRequest(url, hsuser = None, hspass = None):
    request = urllib2.Request(url)
    request.add_header('Content-Type', 'application/x-www-form-urlencoded')
    request.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3')
    request.add_header('Origin', 'http://www4.hockeystreams.com')
    request.add_header('Referer', 'http://www4.hockeystreams.com/')
    if hsuser != None and hspass != None:
        request.add_header('Cookie', 'hsuser=' + hsuser + '; hspass=' + hspass)

    return request
